package com.own.stu.apm.agent.core.plugin.interceptor.enhence;

import com.own.stu.apm.agent.core.plugin.loader.InterceptorInstanceLoader;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.concurrent.Callable;

@Slf4j
public class StaticMethodIntercept {

    StaticMethodsAroundInterceptor staticMethodsAroundInterceptor = null;

    public StaticMethodIntercept(String methodInterceptor, ClassLoader classLoader) {
        try {
            InterceptorInstanceLoader.load(methodInterceptor, classLoader);
        } catch (Exception e) {
            log.error("load StaticMethodIntercept :{} fail ", methodInterceptor, e);
        }
    }

    @RuntimeType
    public Object intercept(
            @Origin Class clazz,
            @Origin Method method,
            @AllArguments Object[] allMethodArgs,
            @Super Object targetObj2,
            @SuperCall Callable<?> zCall
    ) throws Throwable {

        try {
            staticMethodsAroundInterceptor.beforeMethod(clazz, method, allMethodArgs, method.getParameterTypes());
        } catch (Exception e) {
            log.error("class {} before exec static method {} intercept fail", clazz, method.getName(), e);
        }

        Object result = null;
        try {
            result = zCall.call();
        } catch (Throwable e) {
            try {
                staticMethodsAroundInterceptor.handleEx(clazz, method, allMethodArgs, method.getParameterTypes(), e);
            } catch (Throwable t) {
                log.error("class {} handle static method {} fail", clazz, method.getName(), t);
            }
            throw e;
        } finally {
            try {
                result = staticMethodsAroundInterceptor.afterMethod(clazz, method, allMethodArgs, method.getParameterTypes(), result);
            } catch (Throwable t) {
                log.error("class {} after exec static method {} intercept fail", clazz, method.getName(), t);
            }
        }
        return result;
    }
}
